#include <fstream>
#include <iostream>
#include <streambuf>

using namespace std;

#include <gtest/gtest.h>

#include "utils/json.hpp"

using namespace nlohmann;

namespace ns {
typedef struct _RetinaConfig {
    string name;
    vector<vector<int>> min_sizes;
    vector<int> steps;
    vector<float> variance;
    bool clip;
    float loc_weight;
    bool gpu_train;
    int batch_size;
    int ngpu;
    int epoch;
    int decay1;
    int decay2;
    int image_size;
    bool pretrain;
    map<string, int> return_layers;
    int in_channel;
    int out_channel;
} RetinaConfig;

void to_json(json& j, const RetinaConfig& p) {
    j = json{{"name", p.name},
             {"min_sizes", p.min_sizes},
             {"steps", p.steps},
             {"variance", p.variance},
             {"clip", p.clip},
             {"loc_weight", p.loc_weight},
             {"gpu_train", p.gpu_train},
             {"batch_size", p.batch_size},
             {"ngpu", p.ngpu},
             {"epoch", p.epoch},
             {"decay1", p.decay1},
             {"decay2", p.decay2},
             {"image_size", p.image_size},
             {"pretrain", p.pretrain},
             {"return_layers", p.return_layers},
             {"in_channel", p.in_channel},
             {"out_channel", p.out_channel}};
}

void from_json(const json& j, RetinaConfig& p) {
    j.at("name").get_to(p.name);
    j.at("min_sizes").get_to(p.min_sizes);
    j.at("steps").get_to(p.steps);
    j.at("variance").get_to(p.variance);
    j.at("clip").get_to(p.clip);
    j.at("loc_weight").get_to(p.loc_weight);
    j.at("gpu_train").get_to(p.gpu_train);
    j.at("batch_size").get_to(p.batch_size);
    j.at("ngpu").get_to(p.ngpu);
    j.at("epoch").get_to(p.epoch);
    j.at("decay1").get_to(p.decay1);
    j.at("decay2").get_to(p.decay2);
    j.at("image_size").get_to(p.image_size);
    j.at("pretrain").get_to(p.pretrain);
    j.at("return_layers").get_to(p.return_layers);
    j.at("in_channel").get_to(p.in_channel);
    j.at("out_channel").get_to(p.out_channel);
}
}  // namespace ns

TEST(test_10, json_test) {
    std::cout << "jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj" << std::endl;
    std::ifstream in("/home/wd/data/github/c-interview/doc/test.json");
    if (in.is_open()) {
        // std::string json_str(std::istream_iterator<char>(in),
        //                      std::istream_iterator<char>());

        // auto js = json::parse(json_str);
        // std::cout << "json_str: " << js.c_str() << std::endl;
        json js;
        in >> js;
        auto pp = js.get<ns::RetinaConfig>();
        std::cout << "return_layers: " << pp.return_layers["stage1"] << std::endl;
        std::cout << "min_sizes: " << pp.min_sizes.size() << std::endl;
        std::cout << "js: " << js << std::endl;
    }
}